package com.niiwoo.civet.account.service.dubbo;

import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.PageInfo;
import com.niiwoo.civet.account.BillBaseDubboService;
import com.niiwoo.civet.account.dao.entity.*;
import com.niiwoo.civet.account.dao.mapper.OrgBillBaseMapper;
import com.niiwoo.civet.account.dao.mapper.UserBillBaseMapper;
import com.niiwoo.civet.account.dto.request.BillDailySheetRequestDTO;
import com.niiwoo.civet.account.dto.request.BillQueryRequest;
import com.niiwoo.civet.account.dto.request.UserBillBaseRequestDTO;
import com.niiwoo.civet.account.dto.response.BillDailySheetResponseDTO;
import com.niiwoo.civet.account.dto.response.NiiwooBillRespDTO;
import com.niiwoo.civet.account.dto.response.UserBillBaseResponseDTO;
import com.niiwoo.civet.account.enums.BillUserTypeEnum;
import com.niiwoo.civet.account.enums.InoutTypeEnum;
import com.niiwoo.civet.account.enums.OrderTypeEnum;
import com.niiwoo.civet.account.service.local.AccountService;
import com.niiwoo.civet.account.service.local.bill.BillBaseService;
import com.niiwoo.civet.account.service.local.bill.NiiwooBillGuaranteeService;
import com.niiwoo.civet.account.service.local.bill.NiiwooBillPlateformService;
import com.niiwoo.civet.account.service.local.bill.NiiwooBillService;
import com.niiwoo.tripod.provider.dto.response.PageResponseDTO;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author Jaylin
 * @Date 2018-05-22
 * @Description billBaseDubboService实现类
 */
@Service(version = "1.0.0")
public class BillBaseDubboServiceImpl implements BillBaseDubboService{

    @Autowired
    private BillBaseService billBaseService;
    @Autowired
    private NiiwooBillService userBillService;
    @Autowired
    private NiiwooBillGuaranteeService niiwooBillGuaranteeService;
    @Autowired
    private NiiwooBillPlateformService niiwooBillPlateformService;
    @Autowired
    private AccountService accountService;

    @Autowired
    private UserBillBaseMapper userBillBaseMapper;
    @Autowired
    private OrgBillBaseMapper orgBillBaseMapper;

    @Override
    public PageResponseDTO<UserBillBaseResponseDTO> pageUserBillBaseList(UserBillBaseRequestDTO requestDTO) {
        Assert.notNull(requestDTO.getUserId(),"查询用户账单,userId不能为空");

        PageResponseDTO<UserBillBaseResponseDTO> pageResponseDTO = new PageResponseDTO<>();
        PageInfo<UserBillBase> pageInfo = billBaseService.pageBillBase(requestDTO);

        pageResponseDTO.setTotalPage(pageInfo.getPages());
        pageResponseDTO.setTotalCount(Long.valueOf(pageInfo.getTotal()).intValue());
        pageResponseDTO.setItems(this.transUserBillBaseResponseDTOs(pageInfo.getList()));

        return pageResponseDTO;
    }

    @Override
    public List<UserBillBaseResponseDTO> listBillBaseList(UserBillBaseRequestDTO requestDTO) {
        Assert.notNull(requestDTO.getUserId(),"查询用户账单,userId不能为空");

        requestDTO.setPageNumber(1);
        requestDTO.setPageSize(Integer.MAX_VALUE);
        PageInfo<UserBillBase> pageInfo = billBaseService.pageBillBase(requestDTO);
        List<UserBillBaseResponseDTO> responseDTOList = this.transUserBillBaseResponseDTOs(pageInfo.getList());
        return responseDTOList;
    }

    @Override
    public UserBillBaseResponseDTO queryUserBillBase(String userId, Long billBaseId) {
        Assert.hasLength(userId,"userId不能为空");
        Assert.notNull(billBaseId,"billBaseId不能为空");
        UserBillBase userBillBase = billBaseService.getUserBillBaseById(billBaseId, userId);
        return this.transUserBillBaseResponseDTO(userBillBase);
    }

    @Override
    public List<UserBillBaseResponseDTO> queryBackSourceUserBillBases(String userId, Long billBaseId) {
        Assert.hasLength(userId,"userId不能为空");
        Assert.notNull(billBaseId,"billBaseId不能为空");
        UserBillBaseExample example = new UserBillBaseExample();
        UserBillBaseExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andBackSourceBillIdEqualTo(billBaseId);
        List<UserBillBase> userBillBaseList = userBillBaseMapper.selectByExample(example);
        return transUserBillBaseResponseDTOs(userBillBaseList);
    }

    @Override
    public List<NiiwooBillRespDTO> listBillListByBillBaseId(Long billBaseId, String userId) {
        Assert.notNull(billBaseId,"查询用户账单,billBaseId不能为空");
        Assert.notNull(userId,"查询用户账单,inOutType不能为空");

        BillQueryRequest billQueryRequest = new BillQueryRequest();
        billQueryRequest.setUserId(userId);
        billQueryRequest.setBillBaseId(billBaseId);
        List<NiiwooBill> userBills = userBillService.listNiiwooBills(billQueryRequest);
        List<NiiwooBillRespDTO> billRespDTOS = new ArrayList<>();
        for (NiiwooBill userBill : userBills) {
            NiiwooBillRespDTO  respDTO = new NiiwooBillRespDTO();
            BeanUtils.copyProperties(userBill,respDTO);
            billRespDTOS.add(respDTO);
        }
        return billRespDTOS;
    }

    @Override
    public BigDecimal totalAmount(UserBillBaseRequestDTO requestDTO) {
        Assert.notNull(requestDTO,"requestDTO对象不能为空");
        Assert.notNull(requestDTO.getUserId(),"查询用户账单,userId不能为空");
        Assert.notNull(requestDTO.getInOutType(),"查询用户账单,inOutType不能为空");

        BigDecimal totalAmount = billBaseService.totalAmount(requestDTO);
        return totalAmount;
    }

    @Override
    public List<BillDailySheetResponseDTO> getBillDailySheet(BillDailySheetRequestDTO billDailySheetRequestDTO){
        DateTime dateTime = DateTime.parse(billDailySheetRequestDTO.getYearMonthDay());
        DateTime startDateTime = dateTime.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0);
        DateTime endDateTime = dateTime.withHourOfDay(23).withMinuteOfHour(59).withSecondOfMinute(59);

        //查询用户账单
        UserBillBaseExample userBillBaseExample = new UserBillBaseExample();
        UserBillBaseExample.Criteria userBillBaseExampleCriteria = userBillBaseExample.createCriteria();
        userBillBaseExampleCriteria.andCreateTimeGreaterThanOrEqualTo(startDateTime.toDate());
        userBillBaseExampleCriteria.andCreateTimeLessThanOrEqualTo(endDateTime.toDate());
        List<UserBillBase> userBillBaseList = userBillBaseMapper.selectByExample(userBillBaseExample);

        //查询机构的账单
        String yearMonthDay = dateTime.toString("yyyy-MM-dd");
        OrgBillBaseExample orgBillBaseExample = new OrgBillBaseExample();
        OrgBillBaseExample.Criteria orgBillBaseExampleCriteria = orgBillBaseExample.createCriteria();
        orgBillBaseExampleCriteria.andYearMonthDayEqualTo(yearMonthDay);
        List<OrgBillBase> orgBillBaseList = orgBillBaseMapper.selectByExample(orgBillBaseExample);

        //组装结果
        List<BillDailySheetResponseDTO> userbillDailySheetResponseDTOList = userBillBaseList.stream().map(userBillBase -> {
            BillDailySheetResponseDTO billDailySheetResponseDTO = new BillDailySheetResponseDTO();
            billDailySheetResponseDTO.setId(userBillBase.getId());
            billDailySheetResponseDTO.setUserId(userBillBase.getUserId());
            billDailySheetResponseDTO.setUserAccountNo(accountService.loadAccountById(userBillBase.getAccountId()).getAccountNo());
            billDailySheetResponseDTO.setBillUserType(userBillBase.getBillType());
            if(InoutTypeEnum.OUT_TYPE == InoutTypeEnum.getEnumByCode(userBillBase.getInoutType())){
                billDailySheetResponseDTO.setAmount(userBillBase.getAmount().negate());
            }else {
                billDailySheetResponseDTO.setAmount(userBillBase.getAmount());
            }
            billDailySheetResponseDTO.setTransactionTime(userBillBase.getCreateTime());
            billDailySheetResponseDTO.setOrderType(userBillBase.getOrderType());
            billDailySheetResponseDTO.setRemark(OrderTypeEnum.enumOf(userBillBase.getOrderType()).getDesc());
            billDailySheetResponseDTO.setBalanceAmount(userBillBase.getBalanceAmount());
            billDailySheetResponseDTO.setProjectId(userBillBase.getProjectId());

            return billDailySheetResponseDTO;
        }).collect(Collectors.toList());

        List<BillDailySheetResponseDTO> orgbillDailySheetResponseDTOList = orgBillBaseList.stream().map(orgBillBase -> {
            BillDailySheetResponseDTO billDailySheetResponseDTO = new BillDailySheetResponseDTO();
            billDailySheetResponseDTO.setId(orgBillBase.getId());
            billDailySheetResponseDTO.setUserId(orgBillBase.getUserId());
            billDailySheetResponseDTO.setUserAccountNo(accountService.loadAccountById(orgBillBase.getAccountId()).getAccountNo());
            billDailySheetResponseDTO.setBillUserType(orgBillBase.getBillType());
            if(InoutTypeEnum.OUT_TYPE == InoutTypeEnum.getEnumByCode(orgBillBase.getInoutType())){
                billDailySheetResponseDTO.setAmount(orgBillBase.getAmount().negate());
            }else {
                billDailySheetResponseDTO.setAmount(orgBillBase.getAmount());
            }
            billDailySheetResponseDTO.setTransactionTime(orgBillBase.getCreateTime());
            billDailySheetResponseDTO.setOrderType(orgBillBase.getOrderType());
            billDailySheetResponseDTO.setRemark(OrderTypeEnum.enumOf(orgBillBase.getOrderType()).getDesc());
            billDailySheetResponseDTO.setBalanceAmount(orgBillBase.getBalanceAmount());
            billDailySheetResponseDTO.setProjectId(orgBillBase.getProjectId());

            return billDailySheetResponseDTO;
        }).collect(Collectors.toList());


        List<BillDailySheetResponseDTO> billDailySheetResponseDTOList = new ArrayList<>();
        billDailySheetResponseDTOList.addAll(userbillDailySheetResponseDTOList);
        billDailySheetResponseDTOList.addAll(orgbillDailySheetResponseDTOList);

        billDailySheetResponseDTOList.forEach(e ->{
            //获取relationUserIds和relationAccountNos
            OrderTypeEnum orderTypeEnum = OrderTypeEnum.enumOf(e.getOrderType());
            if(OrderTypeEnum.RECHARGE == orderTypeEnum || OrderTypeEnum.WITHDRAW == orderTypeEnum){
                return;
            }
            Set<Long> relationAccountIds = null;
            BillUserTypeEnum billUserTypeEnum = BillUserTypeEnum.getEnumByCode(e.getBillUserType());
            if(BillUserTypeEnum.GENERAL == billUserTypeEnum){
                List<NiiwooBill> billFlows = userBillService.listNiiwooBillsByBaseId(e.getId(), e.getUserId());
                relationAccountIds = billFlows.stream().map(billFlow -> billFlow.getRelationAccountId()).collect(Collectors.toSet());
            }else if (BillUserTypeEnum.GUARANTEE_AGENCY == billUserTypeEnum || BillUserTypeEnum.COOPERATE_AGENCY == billUserTypeEnum){
                List<NiiwooBillGuarantee> billFlows = niiwooBillGuaranteeService.listByBaseId(e.getId(), yearMonthDay);
                relationAccountIds = billFlows.stream().map(billFlow -> billFlow.getRelationAccountId()).collect(Collectors.toSet());
            }else if (BillUserTypeEnum.PLATFORM == billUserTypeEnum) {
                List<NiiwooBillPlatform> billFlows = niiwooBillPlateformService.listByBaseId(e.getId(), yearMonthDay);
                relationAccountIds = billFlows.stream().map(billFlow -> billFlow.getRelationAccountId()).collect(Collectors.toSet());
            }else {
                throw new RuntimeException("billType不正确:"+ billUserTypeEnum);
            }

            List<AccountBase> accountBases = accountService.loadAccountsByIds(relationAccountIds);
            Set<String> relationUserIdSet = accountBases.stream().map(accountBase -> accountBase.getUserId()).collect(Collectors.toSet());
            Set<String> relationAccountNoSet = accountBases.stream().map(accountBase -> accountBase.getAccountNo()).collect(Collectors.toSet());
            e.setRelationUserIds(StringUtils.join(relationUserIdSet, ","));
            e.setRelationAccountNos(StringUtils.join(relationAccountNoSet, ","));
        });





        return billDailySheetResponseDTOList;

    }




    private List<UserBillBaseResponseDTO> transUserBillBaseResponseDTOs(List<UserBillBase> userBillBaseList) {
        return userBillBaseList.stream().map(userBillBase -> transUserBillBaseResponseDTO(userBillBase)).collect(Collectors.toList());
    }


    private UserBillBaseResponseDTO transUserBillBaseResponseDTO(UserBillBase billBase){
        UserBillBaseResponseDTO responseDTO = new UserBillBaseResponseDTO();
        BeanUtils.copyProperties(billBase, responseDTO);
        responseDTO.setBillBaseId(billBase.getId());
        return responseDTO;
    }

}
